package com.gradecak.alfresco.mvc.servlet;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.alfresco.service.ServiceRegistry;
import org.springframework.beans.BeansException;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.extensions.webscripts.Description;
import org.springframework.extensions.webscripts.DescriptionImpl;
import org.springframework.extensions.webscripts.TransactionParameters;
import org.springframework.extensions.webscripts.Description.RequiredAuthentication;
import org.springframework.extensions.webscripts.Description.RequiredTransaction;
import org.springframework.extensions.webscripts.Description.TransactionCapability;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.WebUtils;


public class FrameworkDispatcherServlet extends DispatcherServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 7192691111191267359L;

	/** Flag used to detect whether onRefresh has already been called */
	private boolean refreshEventReceived = false;

	private WebApplicationContext parentWebApplicationContext;

	public FrameworkDispatcherServlet(
			WebApplicationContext webApplicationContext) {
		this.parentWebApplicationContext = webApplicationContext;
	}

	@Override
	protected WebApplicationContext initWebApplicationContext()
			throws BeansException {

		WebApplicationContext wac = createWebApplicationContext(parentWebApplicationContext);

		if (!this.refreshEventReceived) {
			// Apparently not a ConfigurableApplicationContext with refresh
			// support:
			// triggering initial onRefresh manually here.
			onRefresh(wac);
		}

		if (wac == null) {
			wac = super.initWebApplicationContext();
		}

		return wac;

	}

	public void onApplicationEvent(ContextRefreshedEvent event) {
		this.refreshEventReceived = true;
		onRefresh(event.getApplicationContext());
	}

	@Override
	public void service(final ServletRequest req, final ServletResponse res)
			throws ServletException, IOException {
		doService(req, res);
	}

	protected void doService(final ServletRequest req, final ServletResponse res)
			throws ServletException, IOException {
		super.service(req, res);
	}

	public Description getDescription(FrameworkServletRequestProxy request)
			throws Exception {

		HandlerExecutionChain mappedHandler = getHandler(request, false);
		if (mappedHandler == null || mappedHandler.getHandler() == null) {
			return null;
		}

		// HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
		Class<?> handlerClass = ClassUtils.getUserClass(mappedHandler
				.getHandler());
		Method m = new ServletHandlerMethodResolver(handlerClass)
				.resolveHandlerMethod(request);

		Transactional tx = AnnotationUtils.findAnnotation(m,
				Transactional.class);

		DescriptionImpl serviceDesc = new DescriptionImpl();
		TransactionParameters trxParams = new TransactionParameters();
		
		RequiredTransaction reqTrx = (tx != null && Propagation.REQUIRED == tx.propagation()) ? RequiredTransaction.required : RequiredTransaction.none;
		trxParams.setRequired(reqTrx);
		
		TransactionCapability trxCapability = (tx != null && !tx.readOnly()) ? TransactionCapability.readwrite : TransactionCapability.readonly;
        trxParams.setCapability(trxCapability);
		        
        serviceDesc.setRequiredTransactionParameters(trxParams);
		return serviceDesc;
	}
}
